package com.dd.cloud.user.service.classroom.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.user.config.MediaConfig;
import com.dd.cloud.common.constants.ClassroomConstants;
import com.dd.cloud.user.entity.classroom.MediaClassify;
import com.dd.cloud.user.entity.classroom.MediaContent;
import com.dd.cloud.user.entity.classroom.MediaSection;
import com.dd.cloud.user.enums.ExceptionEnum;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.user.mapper.classroom.MediaSectionMapper;
import com.dd.cloud.user.req.classroom.*;
import com.dd.cloud.user.res.classroom.MediaSectionPageRes;
import com.dd.cloud.user.service.classroom.IMediaClassifyService;
import com.dd.cloud.user.service.classroom.IMediaContentService;
import com.dd.cloud.user.service.classroom.IMediaSectionService;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.utils.ExtUtils;
import com.dd.cloud.common.utils.ObjectUtils;
import com.dd.cloud.common.utils.ValidatorUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 媒体小节说明表 服务实现类
 * </p>
 *
 * @author czg
 * @since 2022-09-14
 */
@Service
public class MediaSectionServiceImpl extends ServiceImpl<MediaSectionMapper, MediaSection> implements IMediaSectionService {

    @Autowired
    private IMediaClassifyService mediaClassifyService;
    @Autowired
    private MediaTheadPoolService mediaTheadPoolService;
    @Autowired
    public MediaConfig mediaConfig;
    @Autowired
    private IMediaContentService mediaContentService;


    /**
     * 分页查询视频小节列表
     *
     * @param req
     * @return
     */
    @Override
    public Page<MediaSectionPageRes> getSectionPage(MediaSectionPageReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        getBaseMapper().updateMediaSectionReorder(null);

        req.setUserType(loginInfo.getType());
        if (req.getClassifyId() != null) {
            getBaseMapper().updateMediaSectionReorder(req.getClassifyId());
        }
        if (loginInfo.getType() != LoginInfo.UserType.ADMIN) {
            req.setStatus(null);
        }
        if (!StringUtils.isBlank(req.getStatus())) {
            req.setStatusStr(req.getStatus().split(","));
        }
        Page<MediaSectionPageRes> page = req.pagePojo();
        page = getBaseMapper().getMediaSectionPage(page, req);
        return page;
    }

    /**
     * 添加小节播放次数
     * 小节和视频都增加播放次数
     * @param id 小节id,
     */
    @Override
    public void addSectionPlays(Integer id) {
        MediaContent mediaContent = mediaContentService.getById(id);
        if (mediaContent == null){
            return;
        }
        if (mediaContent.getPlays() == null) {
            mediaContent.setPlays(1);
        } else {
            mediaContent.setPlays(mediaContent.getPlays() + 1);
        }
        mediaContentService.updateById(mediaContent);
        MediaSection section = getById(mediaContent.getSectionId());
        if (section == null) {
            return;
        }
        if (section.getPlays() == null) {
            section.setPlays(1);
        } else {
            section.setPlays(section.getPlays() + 1);
        }
        updateById(section);
    }

    /**
     * 添加视频 ,默认禁用
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createSection(CreateMediaSectionReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        if (!mediaClassifyService.checkClassifyExists(req.getClassifyId())) {
            throw new ZekeException(ExceptionEnum.MEDIA_CLASSIFY_IS_NOT_EXISTS);
        }
        QueryWrapper<MediaSection> qw = new QueryWrapper<>();
        qw.lambda().eq(MediaSection::getStatus, ClassroomConstants.SectionStatus.NORMAL)
                .eq(MediaSection::getClassifyId, req.getClassifyId())
                .eq(MediaSection::getName, req.getName());
        List<MediaSection> list = list(qw);
        if (list != null && !list.isEmpty()) {
            throw new ZekeException(400, "小节名已存在");
        }
        int sort = cumSectionSort(req.getSort(), req.getClassifyId(), null);
        MediaSection section = new MediaSection();
        BeanUtils.copyProperties(req, section);
        section.setStatus(ClassroomConstants.SectionStatus.HIDDEN);
        section.setCreateId(loginInfo.getId());
        section.setSort(sort);
        section.setPlays(0);
        int flag = getBaseMapper().insert(section);
        if (flag <= 0) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
        if (req.getContentList() != null && !req.getContentList().isEmpty()) {
            //连带了视频, 上传视频
            for (int i = 0; i < req.getContentList().size(); i++) {
                CreateMediaContentReq contentReq = req.getContentList().get(i);
                UploadMediaContentListReq mediaContentReq = new UploadMediaContentListReq();
                mediaContentReq.setFile(contentReq.getFile());
                mediaContentReq.setIndex(i);
                mediaContentReq.setName(contentReq.getName());
                mediaContentService.uploadMedia(mediaContentReq, section, 1);
                try {
                    //mediaTheadPoolService.uploadMedia(mediaContentReq, loginInfo);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 修改小节
     *
     * @param req
     */
    @Override
    //@Transactional(rollbackFor = Exception.class)
    public void updateSection(UpdateMediaSectionReq req, MultipartFile[] files) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
//        if (req.getContentList() != null && req.getContentList().size() != files.length){
//            throw new ZekeException(400, "参数列表与视频列表个数不一致");
//        }
        MediaSection section = getById(req.getId());
        if (section == null) {
            throw new ZekeException(400, "视频内容id不存在");
        }
        if (!req.getClassifyId().equals(section.getClassifyId())) {
            if (!mediaClassifyService.checkClassifyExists(req.getClassifyId())) {
                throw new ZekeException(ExceptionEnum.MEDIA_CLASSIFY_IS_NOT_EXISTS);
            }
        }

        if (!req.getName().equals(section.getName())) {
            //修改了小节标题
            QueryWrapper<MediaSection> qw = new QueryWrapper<>();
            qw.lambda().eq(MediaSection::getStatus, ClassroomConstants.SectionStatus.NORMAL)
                    .eq(MediaSection::getClassifyId, req.getClassifyId())
                    .eq(MediaSection::getName, req.getName());
            List<MediaSection> list = list(qw);
            if (list != null && !list.isEmpty()) {
                throw new ZekeException(400, "小节名已存在");
            }
        }

        if (req.getVaild() == 1) {
            int sort = cumSectionSort(req.getSort(), req.getClassifyId(), null);
            BeanUtils.copyProperties(req, section);
            section.setSort(sort);
            section.setUpdateDate(LocalDateTime.now());
            boolean flag = updateById(section);
            if (!flag) {
                throw new ZekeException(ZkExceptionEnum.UPDATE_ERROR);
            }
        }
        String msg = " ";
        int succ = 0;
        if (req.getContentList() != null && !req.getContentList().isEmpty()) {
            if (req.getContentList().size() > 200) {
                throw new ZekeException(400, "视频数据不能超过200个");
            }
            //mediaContentService.addOrUpdateCheackMediaName(req.getContentList(), section.getId());
            //连带了视频, 上传视频
            int mediaSort = 0;
            for (int i = 0; i < req.getContentList().size(); i++) {
                CreateMediaContentReq contentReq = req.getContentList().get(i);
                if (!StringUtils.isBlank(contentReq.getName()) && contentReq.getName().length() > 20) {
                    if (StringUtils.isBlank(msg)) {
                        msg = "视频名称超过20字符:";
                    }
                    msg = msg + contentReq.getName() + ", ";
                    continue;
                }
                UploadMediaContentListReq mediaContentReq = new UploadMediaContentListReq();
                mediaContentReq.setId(contentReq.getId());
                if (req.getVaild() == 1 && contentReq.getIsUpdateMedia() == 1) {
                    if (mediaSort > files.length) {
                        throw new ZekeException(400, "参数列表与视频列表个数不一致");
                    }
                    mediaContentReq.setFile(files[mediaSort]);
                    mediaSort++;
                }
                if (req.getVaild() == 1 && mediaContentReq.getId() == null
                        && contentReq.getIsUpdateMedia() != 1) {
                    msg = msg + "视频id为空需要上传视频与isUpdateMedia参数为1";
                    //throw new ZekeException(400, "视频id为空需要上传视频与isUpdateMedia参数为1");
                    continue;
                }
                mediaContentReq.setIndex(i);
                mediaContentReq.setName(contentReq.getName());
                String errMsg = mediaContentService.uploadMedia(mediaContentReq, section, req.getVaild());
                if (!StringUtils.isBlank(errMsg)) {
                    msg = msg + errMsg;
                } else {
                    succ++;
                }
                //mediaTheadPoolService.uploadMedia(mediaContentReq, loginInfo);
            }
        }
        if (succ < req.getContentList().size()) {
            if (req.getVaild() == 1 && files.length > 0) {
                throw new ZekeException(400, "视频信息修改成功, 其中" + succ + "条视频小节修改和上传成功, "
                        + (req.getContentList().size() - succ) + "条视频小节修改和上传失败, 原因-" + msg);
            } else {
                throw new ZekeException(400, msg);
            }
        }
    }

    /**
     * 修改视频小节状态
     *
     * @param id
     * @param status
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSectionStatus(Integer id, Integer status) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
        MediaSection mediaSection = getById(id);
        if (mediaSection == null || mediaSection.getStatus() == ClassroomConstants.ClassifyStatus.DEL) {
            throw new ZekeException(400, "视频不存在");
        }
        if (!ObjectUtils.refrect(ClassroomConstants.SectionStatus.class, status)) {
            throw new ZekeException(ZkExceptionEnum.STATUS_DATA_ERROR);
        }
        if (mediaSection.getStatus().equals(status)) {
            return;
        }
        if (mediaSection.getStatus() == ClassroomConstants.SectionStatus.RELETED && status == ClassroomConstants.SectionStatus.NORMAL) {
            throw new ZekeException(400, "启用视频无效,该视频大类未启用");
        }
        if (mediaSection.getStatus() == ClassroomConstants.SectionStatus.HIDDEN && status == ClassroomConstants.SectionStatus.NORMAL) {
            //throw new ZekeException(400, "启用视频无效,该视频大类未启用");
            if (StringUtils.isBlank(mediaSection.getImg())){
                throw new ZekeException(400, "启用视频无效,请添加视频封面");
            }
            QueryWrapper<MediaContent> mc = new QueryWrapper<>();
            mc.lambda().eq(MediaContent::getSectionId, id)
                    .ne(MediaContent::getStatus, ClassroomConstants.ContentStatus.DEL);
            int countContent = mediaContentService.count(mc);
            if (countContent <= 0){
                throw new ZekeException(400, "启用视频无效,该视频无小节内容, 请添加后启用");
            }
        }
        mediaSection.setStatus(status);
        boolean flag = updateById(mediaSection);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.UPDATE_ERROR);
        }
        if (status == ClassroomConstants.SectionStatus.HIDDEN) {
            status = ClassroomConstants.ContentStatus.RELETED;
        }
        mediaContentService.updateContentStatusBySection(id, status);
    }

    /**
     * 操作大类下所有视频的状态, 连带操作,比如禁用/删除大类 大类下所有的视频都要此状态
     *
     * @param classifyId
     * @param status
     */
    @Override
    public void updateSectionStatusByClassify(Integer classifyId, Integer status) {
        if (!ObjectUtils.refrect(ClassroomConstants.SectionStatus.class, status)) {
            throw new ZekeException(ZkExceptionEnum.STATUS_DATA_ERROR);
        }
        UpdateWrapper<MediaSection> uw = new UpdateWrapper<>();
        uw.lambda().set(MediaSection::getStatus, status)
                .in(MediaSection::getStatus, new Integer[]{ClassroomConstants.SectionStatus.NORMAL, ClassroomConstants.SectionStatus.RELETED})
                .eq(MediaSection::getClassifyId, classifyId);
        update(uw);
    }

    /**
     * 导入视频小节信息 倒入的信息无视频, 先禁用 20221026
     *
     * @param file excel文件
     */
    @Override
    public void importSection(MultipartFile file) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
        if (file == null) {
            throw new ZekeException(400, "请上传文件");
        }
        if (!file.getOriginalFilename().contains(".xlsx") && !file.getOriginalFilename().contains(".xls")) {
            throw new ZekeException(400, "只支持xlsx和xls文件格式");
        }

        List<ImportMediaSectionReq> list = new ArrayList<>();
        try {
            list = ExtUtils.importExcel(file, 1, 1, ImportMediaSectionReq.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ZekeException(400, "解析Excel失败");
        }
        int size = list.size();
        if (list.isEmpty()) {
            throw new ZekeException(400, "文档无数据");
        }
        //查询类型 ,并赋值类型id
        for (ImportMediaSectionReq req :
                list) {
            //手动验证数据
            ValidatorUtils.verify(req, ImportMediaSectionReq.class);
            QueryWrapper<MediaClassify> qw = new QueryWrapper<>();
            qw.lambda().eq(MediaClassify::getClassify, req.getClassify())
                    .eq(MediaClassify::getStatus, ClassroomConstants.ClassifyStatus.NORMAL);
            MediaClassify classify = mediaClassifyService.getOne(qw);
            if (classify != null) {
                req.setClassifyId(classify.getId());
            }
        }
        //移除不存在的类型
        List<String> notExists = new LinkedList<>();
        Iterator<ImportMediaSectionReq> it = list.iterator();
        while (it.hasNext()) {
            //移除类型不存在的视频
            ImportMediaSectionReq importReq = it.next();
            if (importReq.getClassifyId() == null) {
                notExists.add(importReq.getClassify());
                it.remove();
            }
        }
        if (list.isEmpty()){
            throw new ZekeException(400, "导入失败, 视频类型不存在: " + StringUtils.join(notExists, ","));
        }
        List<String> nameList = new ArrayList<String>(list.stream().map(ImportMediaSectionReq::getName).collect(Collectors.toList()));
        QueryWrapper<MediaSection> qw = new QueryWrapper<>();
        qw.lambda().eq(MediaSection::getStatus, ClassroomConstants.ClassifyStatus.NORMAL)
                .in(MediaSection::getName, nameList);
        List<MediaSection> mediaClassify = list(qw);
        List<String> existsNameList = new LinkedList<>();
        //已经存在的视频名称
        if (!mediaClassify.isEmpty()) {
            existsNameList = mediaClassify.stream().map(MediaSection::getName).collect(Collectors.toList());
        }
        if (!existsNameList.isEmpty()) {
            Iterator<ImportMediaSectionReq> its = list.iterator();
            while (its.hasNext()) {
                //移除名字存在的视频
                ImportMediaSectionReq importReq = its.next();
                if (existsNameList.contains(importReq.getName())) {
                    its.remove();
                }
            }
        }

        List<Integer> sortList = new LinkedList<>();
        for (int i = 0; i < list.size(); i++) {
            ImportMediaSectionReq req = list.get(i);
            if (i > 0){
                sortList.add(list.get(i-1).getSort());
            }
            //重排序
            //getBaseMapper().updateMediaSectionReorder(req.getClassifyId());
            int sort = cumSectionSort(req.getSort(), req.getClassifyId(), sortList);
            MediaSection section = new MediaSection();
            BeanUtils.copyProperties(req, section);
            section.setCreateId(loginInfo.getId());
            section.setStatus(ClassroomConstants.SectionStatus.HIDDEN);
            section.setCreateDate(LocalDateTime.now());
            section.setSort(sort);
            section.setPlays(0);
            boolean flag = save(section);
            if (!flag) {
                throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
            }
            getBaseMapper().updateMediaSectionReorder(req.getClassifyId());
        }

//        if (!saveList.isEmpty()) {
//            Integer flag = getBaseMapper().insertBatchSomeColumn(saveList);
//            if (flag <= 0) {
//                throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
//            }
//        }

        String exMsg = "";
        if (!notExists.isEmpty()) {
            exMsg = "以下视频类型不存在: " + StringUtils.join(notExists, ",");
        }
        if (!existsNameList.isEmpty()) {
            exMsg = exMsg + " 以下视频名称已存在: " + StringUtils.join(existsNameList, ",");
        }
        if (!StringUtils.isBlank(exMsg)) {
            throw new ZekeException(400, list.size() + "条数据导入成功, " +
                    (size - list.size()) + "条数据导入失败, 原因-" + exMsg);
        }
    }

    /**
     * 批量上传视频
     *
     * @param files
     */
    @Override
    public void uploadMedia(MultipartFile[] files, Integer sectionId, LoginInfo loginInfo) {
        List<MediaContent> contentsList = new LinkedList<>();
        String msg = "";
        try {
            for (MultipartFile one : files) {
                MediaContent content = new MediaContent();
                //下载的文件名
                String fileName = one.getOriginalFilename();
                content.setName(fileName);
                content.setCreateId(loginInfo.getId());
                content.setStatus(ClassroomConstants.ContentStatus.NORMAL);
                content.setSectionId(sectionId);
                content.setUrl("vod/" + fileName + "/index.m3u8");
                one.transferTo(new File(mediaConfig.getMediaAddr() + fileName));
                contentsList.add(content);
            }
            mediaContentService.insertBatch(contentsList);
        } catch (Exception e) {
            e.printStackTrace();

            throw new ZekeException(ZkExceptionEnum.UPLOAD_FAILED_ERROE);
        }

    }

    /**
     * 上传多个视频 新增
     */
    @Override
    public void uploadMediaList(UploadMediaContentReq req, MultipartFile[] files) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
        if (req.getVaild() == 1 && req.getMediaList() != null && req.getMediaList().size() != files.length) {
            throw new ZekeException(400, "参数列表与视频列表个数不一致");
        }
        MediaSection section = getById(req.getSectionId());
        if (section == null) {
            throw new ZekeException(400, "小节id不存在");
        }
        section.setUpdateDate(LocalDateTime.now());
        if (req.getVaild() == 1) {
            updateById(section);
        }
        //List<UploadMediaContentListReq> listReqs = req.getMediaList();
        if (req.getVaild() == 1 && files == null || files.length == 0) {
            throw new ZekeException(400, "视频列表不能为空");
        }
        String msg = "";
        List<String> names = req.getMediaList().stream().map(UploadMediaContentListReq::getName).collect(Collectors.toList());
        List<String> exists = mediaContentService.checkMediaNameExists(req.getSectionId(), names);
        if (!exists.isEmpty()) {
            msg = "以下视频名字已存在:" + StringUtils.join(exists, ",");
//            throw new ZekeException(400, "以下视频名字已存在:" + StringUtils.join(exists, ","));
        }
        int succ = 0;
        for (int i = 0; i < req.getMediaList().size(); i++) {
            UploadMediaContentListReq contentReq = req.getMediaList().get(i);
            if (exists.contains(contentReq.getName())) {
                continue;
            }
            if (!StringUtils.isBlank(contentReq.getName()) && contentReq.getName().length() > 20) {
                if (StringUtils.isBlank(msg)) {
                    msg = "视频名称超过20字符:";
                }
                msg = msg + contentReq.getName() + ", ";
                continue;
            }
            if (req.getVaild() == 1) {
                contentReq.setFile(files[i]);
            } else {
                contentReq.setFile(null);
            }
            //mediaTheadPoolService.uploadMedia(contentReq, req.getSectionId());
            String errMsg = mediaContentService.uploadMedia(contentReq, section, req.getVaild());
            if (!StringUtils.isBlank(errMsg)) {
                msg = msg + errMsg;
            } else {
                succ++;
            }
        }
        if (succ < req.getMediaList().size()) {
            if (req.getVaild() == 1) {
                throw new ZekeException(400, succ + "条视频导入成功," + (req.getMediaList().size() - succ)
                        + "条视频导入失败, 原因-" + msg);
            } else {
                throw new ZekeException(400, msg);
            }
        }

    }

    /**
     * id获取视频详情
     * @param id
     * @return
     */
    @Override
    public MediaSectionPageRes getMediaSectionDetail(Integer id) {
        return getBaseMapper().getSectionDetail(id);
    }

    /**
     * @param sort       排序位置
     * @param classifyId 类型id
     * @return 目标位置
     */
    public int cumSectionSort(Integer sort, Integer classifyId, List<Integer> notSort) {
        //先进行重排序
        getBaseMapper().updateMediaSectionReorder(classifyId);
        if (sort == null) {
            QueryWrapper<MediaSection> qu = new QueryWrapper<>();
            //qu.lambda().eq(MediaSection::getClassifyId, classifyId)
            qu.lambda().orderByDesc(MediaSection::getSort)
                    .last("limit 1");
            MediaSection mediaSection = getOne(qu);
            if (mediaSection == null) {
                return 1;
            }
            return mediaSection.getSort() + 1;
        }
        UpdateWrapper<MediaSection> uw = new UpdateWrapper<>();
        uw.lambda().ge(MediaSection::getSort, sort)
//                .eq(MediaSection::getClassifyId, classifyId)
                .setSql("`sort` = `sort` + 1");
        if (notSort != null && !notSort.isEmpty()){
            uw.lambda().notIn(MediaSection::getSort, notSort);
        }
        update(uw);
        return sort;
    }


}
